#include "w25x16.h"
#include "stdbool.h"


extern SPI_HandleTypeDef hspi1;


static void sFLASH_Status(void);
static uint8_t sFLASH_SendByte(uint8_t byte);
static void sFLASH_WriteEnable(void);


static uint8_t sFLASH_SendByte(uint8_t byte)
{
	uint8_t TX_data,RX_data;
	TX_data = byte;
	RX_data = 0;
	HAL_SPI_TransmitReceive(&hspi1, &TX_data,&RX_data,1,0xFF);
  return RX_data;                                      
}


//��Ҫʹ�ñ�������Ҫ�Ѿ�����ͨ��״̬  ��״̬�Ĵ���
static void sFLASH_Status(void)
{
	sFLASH_CS_LOW();
	uint8_t data = 1;
	sFLASH_SendByte(sFLASH_CMD_RDSR);
	while(data)
	{
		data = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
		data = data & sFLASH_BUSY_FLAG;
		HAL_Delay(2000);
	}
	sFLASH_CS_HIGH();	
}


static void sFLASH_WriteEnable(void)
{
	sFLASH_CS_LOW();
	sFLASH_SendByte(sFLASH_CMD_WREN);
	sFLASH_CS_HIGH();	
}


uint16_t sFLASH_ReadID(void)
{
	uint16_t flash_id = 0;
	uint8_t device_id = 0,manufacturer_id = 0;
	sFLASH_CS_LOW();
	sFLASH_SendByte(W25X_ManufactDeviceID);
	sFLASH_SendByte(sFLASH_DUMMY_BYTE);
	sFLASH_SendByte(sFLASH_DUMMY_BYTE);
	sFLASH_SendByte(sFLASH_DUMMY_BYTE);
	manufacturer_id = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
	device_id = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
	sFLASH_CS_HIGH();
	flash_id = (manufacturer_id<<8) | device_id;
	return flash_id;
}




void sFLASH_EraseSector(uint32_t SectorAddr)
{
	sFLASH_WriteEnable();
	sFLASH_CS_LOW();
	sFLASH_SendByte(sFLASH_CMD_SE);
	sFLASH_SendByte((SectorAddr>>16) & 0xFF);
	sFLASH_SendByte((SectorAddr>>8) & 0xFF);
	sFLASH_SendByte((SectorAddr>>0) & 0xFF);
	sFLASH_CS_HIGH();
	
	//�ȴ��������
	sFLASH_Status();
}






void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint32_t NumByteToWrite)
{
	uint16_t Numofpage = 0,Numofbytes = 0,count,offset;
	offset = WriteAddr % sFLASH_SPI_PAGESIZE;
	count = sFLASH_SPI_PAGESIZE - offset;
	if(offset && (NumByteToWrite > sFLASH_SPI_PAGESIZE))
	{
			sFLASH_WritePage(pBuffer,WriteAddr,count);
			NumByteToWrite = NumByteToWrite - count;
			WriteAddr = WriteAddr + count;
		pBuffer = pBuffer + count;
	}
	Numofpage = NumByteToWrite / sFLASH_SPI_PAGESIZE;
	Numofbytes = NumByteToWrite % sFLASH_SPI_PAGESIZE;
	if(Numofpage)
	{
		while(Numofpage--)
		{
			sFLASH_WritePage(pBuffer,WriteAddr,sFLASH_SPI_PAGESIZE);
			pBuffer = pBuffer + sFLASH_SPI_PAGESIZE;
			WriteAddr = WriteAddr + sFLASH_SPI_PAGESIZE;
		}
	}
	if(Numofbytes)
	{
		sFLASH_WritePage(pBuffer,WriteAddr,Numofbytes);
	}
}






bool sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint32_t NumByteToWrite)
{
	if(NumByteToWrite > sFLASH_SPI_PAGESIZE)
	{
		return false;  //�������޷�д��
	}
	
	sFLASH_WriteEnable();  //����д��ʹ��
	sFLASH_CS_LOW();
	sFLASH_SendByte(sFLASH_CMD_WRITE);
	sFLASH_SendByte((WriteAddr>>16) & 0xFF);
	sFLASH_SendByte((WriteAddr>>8) & 0xFF);
	sFLASH_SendByte((WriteAddr>>0) & 0xFF);
	while(NumByteToWrite--)
	{
		sFLASH_SendByte(*pBuffer);
		pBuffer++;
	}
	sFLASH_CS_HIGH();
	
	sFLASH_Status();      //�ȴ�д���
	return true;
}








void sFLASH_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint32_t NumByteToRead)
{
	sFLASH_CS_LOW();
	sFLASH_SendByte(sFLASH_CMD_READ);
	
	sFLASH_SendByte((ReadAddr>>16) & 0xFF);
	sFLASH_SendByte((ReadAddr>>8) & 0xFF);
	sFLASH_SendByte((ReadAddr>>0) & 0xFF);
	for(uint32_t i = 1;i <= NumByteToRead;i++)
	{
		*pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
		pBuffer++;
	}
	sFLASH_CS_HIGH();
	sFLASH_Status();
}









